package com.example.paymentdemo.controller;

import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayConstants;
import com.alipay.api.internal.util.AlipaySignature;
import com.example.paymentdemo.entity.OrderInfo;
import com.example.paymentdemo.service.AliPayService;
import com.example.paymentdemo.service.OrderInfoService;
import com.example.paymentdemo.vo.R;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.util.Map;

@CrossOrigin
@RestController
@RequestMapping("/api/ali-pay")
@Api(tags = "支付宝支付")
@Slf4j
public class AliPayController {
    @Autowired
    private AliPayService aliPayService;

    @Autowired
    private Environment environment;

    @Autowired
    private OrderInfoService orderInfoService;

    @ApiOperation("统一收单下单并支付页面接口的调用")
    @PostMapping("/trade/page/pay/{productId}")
    public R tradePagePay(@PathVariable Long productId) throws AlipayApiException {
        log.info("统一收单下单并支付页面接口的调用");
        //调用并接收表单字符串 改串在前端跳转到支付页面
        String formStr = aliPayService.tradeCreate(productId);

        return R.ok().data("formStr", formStr);

    }

    @ApiOperation("支付的回调接口")
    @PostMapping("/trade/notify")
    public String returnUrl(@RequestParam Map<String, String> params) throws AlipayApiException {
        log.info("支付宝的异步通知参数：{}", params);
        //通知结构校验 不成功则直接返回失败
        if(!inspectNotify(params)){
            return "failure";
        }

        //校验成功 修改订单状态 记录支付日志
        aliPayService.processOrder(params);


        return "success";
    }

    /**
     * 回调通知校验
     * @param params
     * @return
     */
    private boolean inspectNotify(Map<String, String> params) throws AlipayApiException {
        boolean signVerified = AlipaySignature.rsaCheckV1(params,
                environment.getProperty("alipay.alipay-public-key"),
                AlipayConstants.CHARSET_UTF8, AlipayConstants.SIGN_TYPE_RSA2); //调用SDK验证签名

        if (!signVerified) {
            log.error("验签失败");
            return false;

        } else {
            //校验其他信息 因为 第三方应用是不可信的   订单号 金额 seller_id  app_id

            String orderNo = params.get("out_trade_no");
            OrderInfo order = orderInfoService.getOrderByOrderNo(orderNo);
            if (order==null){//校验订单号
                log.error("订单不存在");
                return false;
            }else {//校验金额
                String totalAmount = params.get("total_amount");//以分为单位的 先转换为元
                int totalAmountInt = new BigDecimal(totalAmount).multiply(BigDecimal.valueOf(100)).intValue();
                if (order.getTotalFee() != totalAmountInt) {
                    log.error("金额不一致");
                    return false;
                } else {//校验商户id
                    String sellerId = params.get("seller_id");
                    if(!environment.getProperty("alipay.seller-id").equals(sellerId)){
                        log.error("商户id不一致");
                        return false;
                    } else {//校验app_id
                        String appId = params.get("app_id");
                        if(!environment.getProperty("alipay.app-id").equals(appId)){
                            log.error("app_id不一致");
                            return false;
                        }else {//所有验证都通过 判断状态
                            String tradeStatus = params.get("trade_status");
                            if (!"TRADE_SUCCESS".equals(tradeStatus)) {
                                log.error("支付未成功");
                                return false;
                            }else {
                                log.info("支付通知验证成功");
                                return true;
                            }
                        }

                    }

                }

            }
        }
    }


    /**
     * 用户取消订单
     * @param orderNo
     * @return
     */
    @ApiOperation("取消订单")
    @PostMapping("/trade/close/{orderNo}")
    public R cancel(@PathVariable String orderNo) throws AlipayApiException {
        log.info("取消订单");
        aliPayService.cancelOrder(orderNo);
        return R.ok().setMessage("订单取消成功");
    }

    /**
     * 查询订单
     * @param orderNo
     * @return
     */
    @ApiOperation("查询订单：测试订单状态用")
    @GetMapping("/trade/query/{orderNo}")
    public R queryOrder(@PathVariable String orderNo) throws AlipayApiException {

        log.info("查询订单");

        String result = aliPayService.queryOrder(orderNo);
        return R.ok().setMessage("查询成功").data("result", result);

    }

    /**
     * 申请退款
     * @param orderNo
     * @param reason
     * @return
     */
    @ApiOperation("申请退款")
    @PostMapping("/trade/refund/{orderNo}/{reason}")
    public R refunds(@PathVariable String orderNo, @PathVariable String reason){
        log.info("申请退款");
        aliPayService.refund(orderNo, reason);
        return R.ok();
    }


    /**
     * 根据账单类型和日期获取账单url地址
     *
     * @param billDate
     * @param type
     * @return
     */
    @ApiOperation("获取账单url")
    @GetMapping("/bill/downloadurl/query/{billDate}/{type}")
    public R queryTradeBill(
            @PathVariable String billDate,
            @PathVariable String type) {
        log.info("获取账单url");
        String downloadUrl = aliPayService.queryBill(billDate, type);
        return R.ok().setMessage("获取账单url成功").data("downloadUrl", downloadUrl);
    }


}
